<?php

namespace Aitels\Foundation\Annotation;

use  Aitels\Foundation\Code\ClassAnalyser;

class ApplicationAnnotationsContainer
{
    protected static $instance;
    protected static $applicationAnnotations = [];
    protected $codeAnalyser;
    protected $annotationReader;
    protected $annotationDefinitions;
    protected $routeAnnotationDefinition;
    protected $listeningAnnotationDefinition;
    protected static $cachePath;

    public static function setCachePath($cachePath)
    {
        self::$cachePath = $cachePath;
    }

    public static function getApplicationAnnotations($name)
    {

//        if (self::cacheExists()) {
//            if(env('APP_ENV')!=='local'){
//                $copy = include self::$cachePath;
//            }else{
//                $copy = self::$applicationAnnotations;
//            }
//        } else {
//            if(env('APP_ENV')!=='local') {
//                self::cacheAnnotation();
//            }
        $copy = self::$applicationAnnotations;
//        }

        foreach ($copy as $file => &$methodsAnnotations) {
            foreach ($methodsAnnotations as $methodName => &$methodAnnotations) {
                foreach ($methodAnnotations as $annotationName => &$annotation) {
                    if ($annotationName !== $name)
                        unset($methodAnnotations[$annotationName]);
                }
                if ($methodAnnotations)
                    $methodAnnotations = $methodAnnotations[$name];
                if (empty($methodAnnotations))
                    unset($methodsAnnotations[$methodName]);
            }
        }

        return $copy;
    }

    public static function loadCache()
    {
        self::$applicationAnnotations = require self::$cachePath;
    }

    public static function cacheAnnotation()
    {
        file_put_contents(self::$cachePath, "<?php" . PHP_EOL . '   return ' . var_export(self::$applicationAnnotations, true) . ';');
    }

    public static function cacheExists()
    {
        return isset(self::$cachePath) && file_exists(self::$cachePath);
    }


    public function __construct(...$annotations)
    {
        $this->codeAnalyser = new ClassAnalyser();
        $this->annotationReader = new AnnotationReader();
        foreach ($annotations as $annotation) {
            $this->annotationDefinitions[] = new $annotation;
        }
    }

    public function handle(\SplFileInfo $file)
    {
        self::$applicationAnnotations = array_merge(self::$applicationAnnotations, $this->getClassAnnotations($file));
    }


    protected function getClassAnnotations(\SplFileInfo $classFile)
    {
        $realPath = $classFile->getRealPath();
        $annotations = [];
        $methodsReflections = $this->codeAnalyser->getHardCodedMethodsReflections($realPath);
        foreach ($methodsReflections as $methodReflection) {
            if ($methodAnnotations = $this->getAnnotations($methodReflection))
                $annotations[$realPath][$methodReflection->getName()] = $methodAnnotations;
        }
        return $annotations;
    }


    protected function getAnnotations(\ReflectionMethod $reflectionMethod)
    {
        $arr = [];
        foreach ($this->annotationDefinitions as $annotationDefinition) {
            if ($routeAnnotation = $this->annotationReader->read($reflectionMethod, $annotationDefinition))
                $arr[$annotationDefinition::NAME] = $routeAnnotation;
        }
        return $arr;
    }


}